home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 93 / applic / sdbcmd.c < prev    next >
C/C++ Source or Header  |  1987-01-15  |  19KB  |  837 lines

  1. /* SDB - command parser */
  2.  
  3. #include "sdbio.h"
  4.  
  5. extern int dbv_token;
  6. extern char dbv_tstring[];
  7. extern int dbv_tvalue;
  8. extern struct ifile *dbv_ifp;
  9. extern struct macro *dbv_macros;
  10. extern int dbv_fold;
  11.  
  12. /* db_parse - parse a command */
  13. int db_parse(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9)
  14.   char *fmt;
  15. {
  16.     int sts;
  17.  
  18.     /* check for a command line */
  19.     if (fmt != NULL)
  20.         db_scan(fmt,a1,a2,a3,a4,a5,a6,a7,a8,a9);
  21.  
  22.     /* determine the statement type */
  23.     switch (db_ntoken()) {
  24.     case ';':    sts = TRUE;
  25.             break;
  26.     case COMPRESS:
  27.         sts = db_squeeze(NULL);
  28.         break;
  29.     case CREATE:
  30.         sts = create();
  31.         break;
  32.     case DEFINE:
  33.             sts = mc_define();
  34.             break;
  35.     case DELETE:
  36.         sts = delete();
  37.         break;
  38.     case EXIT:
  39.         exit();
  40.     case EXPORT:
  41.         sts = db_export(NULL);
  42.         break;
  43.     case EXTRACT:
  44.             sts = db_extract(NULL);
  45.             break;
  46.     case HELP:
  47.             sts = help();
  48.             break;
  49.     case IMPORT:
  50.         sts = db_import(NULL);
  51.         break;
  52.     case INSERT:
  53.         sts = insert();
  54.         break;
  55.     case PRINT:
  56.         sts = print();
  57.         break;
  58.     case SELECT:
  59.             sts = select();
  60.             break;
  61.     case SET:
  62.             sts = set();
  63.             break;
  64.     case SHOW:
  65.             sts = mc_show();
  66.             break;
  67.     case SORT:
  68.             sts = db_sort(NULL);
  69.             break;
  70.     case UPDATE:
  71.         sts = update();
  72.         break;
  73.     default:
  74.         return (db_ferror(SYNTAX));
  75.     }
  76.  
  77.     return (sts);
  78. }
  79.  
  80. /* create - create a new relation */
  81. static int create()
  82. {
  83.     struct relation *rptr;
  84.     char aname[STRINGMAX+1];
  85.     int atype,tcnt,text;
  86.  
  87.     /* get relation name */
  88.     if (db_ntoken() != ID)
  89.     return (db_ferror(SYNTAX));
  90.  
  91.     /* start relation creation */
  92.     if ((rptr = db_rcreate(dbv_tstring)) == NULL)
  93.     return (FALSE);
  94.  
  95.     /* check for attribute list */
  96.     if (db_ntoken() != '(') {
  97.     free(rptr);
  98.     return (db_ferror(SYNTAX));
  99.     }
  100.  
  101.     /* parse the attributes */
  102.     while (TRUE) {
  103.  
  104.     /* get the attribute name */
  105.     if (db_ntoken() != ID) {
  106.         free(rptr);
  107.         return (db_ferror(SYNTAX));
  108.     }
  109.     strcpy(aname,dbv_tstring);
  110.  
  111.     /* get the attribute type */
  112.     db_ntoken();
  113.     if (dbv_token == CHAR)
  114.         atype = TCHAR;
  115.     else if (dbv_token == NUM)
  116.         atype = TNUM;
  117.     else {
  118.         free(rptr);
  119.         return (db_ferror(SYNTAX));
  120.     }
  121.  
  122.     /* get the attribute size */
  123.     if (db_ntoken() != NUMBER) {
  124.         free(rptr);
  125.         return (db_ferror(SYNTAX));
  126.     }
  127.  
  128.     /* add the attribute */
  129.     if (!db_rcattr(rptr,aname,atype,dbv_tvalue)) {
  130.         free(rptr);
  131.         return (FALSE);
  132.     }
  133.  
  134.     /* check for end of attributes */
  135.     if (db_token() != ID)
  136.         break;
  137.     }
  138.  
  139.     /* check for attribute list end */
  140.     if (db_ntoken() != ')') {
  141.     free(rptr);
  142.     return (db_ferror(SYNTAX));
  143.     }
  144.  
  145.     /* check for initial relation size */
  146.     if (db_ntoken() != NUMBER) {
  147.     free(rptr);
  148.     return (db_ferror(SYNTAX));
  149.     }
  150.     tcnt = dbv_tvalue;
  151.  
  152.     /* check for expansion increment */
  153.     if (db_ntoken() != NUMBER) {
  154.     free(rptr);
  155.     return (db_ferror(SYNTAX));
  156.     }
  157.     text = dbv_tvalue;
  158.  
  159.     /* finish relation creation */
  160.     if (!db_rcheader(rptr,text))
  161.         return (FALSE);
  162.     if (!db_rctuples(rptr,tcnt))
  163.         return (FALSE);
  164.     if (!db_rcdone(rptr))
  165.         return (FALSE);
  166.  
  167.     /* return successfully */
  168.     return (TRUE);
  169. }
  170.  
  171. /* insert - insert a tuple into a relation */
  172. static int insert()
  173. {
  174.     struct scan *sptr;
  175.     struct attribute *aptr;
  176.     char aname[ANSIZE+1],avalue[STRINGMAX+1];
  177.     int tcnt,astart,i;
  178.  
  179.     /* get relation name */
  180.     if (db_token() == ID)
  181.         db_ntoken();
  182.     else
  183.         strcpy(dbv_tstring,"sdbcur");
  184.  
  185.     /* make sure that the rest of the line is blank */
  186.     if (!db_flush())
  187.         return (FALSE);
  188.  
  189.     /* open the relation */
  190.     if ((sptr = db_ropen(dbv_tstring)) == NULL)
  191.     return (FALSE);
  192.  
  193.     /* insert tuples */
  194.     for (tcnt = 0; ; tcnt++) {
  195.  
  196.         /* print separator if not the first tuple */
  197.         if (tcnt != 0)
  198.             printf("----\n");
  199.  
  200.         /* get attribute values */
  201.         astart = 1;
  202.         for (i = 0; i < NATTRS; i++) {
  203.  
  204.             /* get a pointer to the current attribute */
  205.         aptr = &sptr->sc_relation->rl_header.hd_attrs[i];
  206.  
  207.         /* check for the last attribute */
  208.         if (aptr->at_name[0] == 0)
  209.         break;
  210.  
  211.         /* get the attribute name */
  212.         strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
  213.  
  214.             /* setup null prompt strings */
  215.             db_prompt(NULL,NULL);
  216.  
  217.         /* prompt and input attribute value */
  218.         while (TRUE) {
  219.         if (dbv_ifp == NULL)
  220.                 if (strlen(aname) < 8)
  221.             printf("%s\t\t: ",aname);
  222.             else
  223.             printf("%s\t: ",aname);
  224.         if (db_gline(avalue) != NULL)
  225.             break;
  226.         }
  227.  
  228.             /* check for last insert */
  229.             if (i == 0 && avalue[0] == EOS)
  230.             break;
  231.  
  232.         /* store the attribute value */
  233.         db_aput(aptr,&sptr->sc_tuple[astart],avalue);
  234.  
  235.             /* update the attribute start */
  236.             astart += aptr->at_size;
  237.         }
  238.  
  239.         /* check for last insert */
  240.         if (avalue[0] == EOS)
  241.             break;
  242.  
  243.         /* store the new tuple */
  244.         if (!db_rstore(sptr)) {
  245.             db_rclose(sptr);
  246.             return (FALSE);
  247.         }
  248.     }
  249.  
  250.     /* close the relation */
  251.     db_rclose(sptr);
  252.  
  253.     /* check number of tuples inserted */
  254.     if (tcnt != 0) {
  255.  
  256.     /* print tuple count */
  257.         printf("[ %d inserted ]\n",tcnt);
  258.     }
  259.     else
  260.     printf("[ none inserted ]\n");
  261.  
  262.     /* return successfully */
  263.     return (TRUE);
  264. }
  265.  
  266. /* delete - delete tuples from a relation */
  267. static int delete()
  268. {
  269.     struct sel *slptr;
  270.     struct srel *srptr;
  271.     int tcnt;
  272.  
  273.     /* parse the retrieval clause */
  274.     if ((slptr = db_retrieve(NULL)) == NULL)
  275.         return (FALSE);
  276.  
  277.     /* loop through the retrieved tuples */
  278.     for (tcnt = 0; db_fetch(slptr); tcnt++)
  279.  
  280.         /* delete the retrieved tuples */
  281.         for (srptr = slptr->sl_rels; srptr != NULL; srptr = srptr->sr_next)
  282.             if (!db_rdelete(srptr->sr_scan)) {
  283.             db_done(slptr);
  284.             return (FALSE);
  285.             }
  286.  
  287.     /* finish the retrieval */
  288.     db_done(slptr);
  289.  
  290.     /* check number of tuples deleted */
  291.     if (tcnt != 0) {
  292.  
  293.     /* print tuple count */
  294.         printf("[ %d deleted ]\n",tcnt);
  295.     }
  296.     else
  297.     printf("[ none deleted ]\n");
  298.  
  299.     /* return successfully */
  300.     return (TRUE);
  301. }
  302.  
  303. /* update - update tuples from a relation */
  304. static int update()
  305. {
  306.     struct sel *slptr;
  307.     struct sattr *saptr;
  308.     struct attribute *aptr;
  309.     char aname[ANSIZE+1],avalue[STRINGMAX+1],*ap;
  310.     int tcnt;
  311.  
  312.     /* parse the selection clause */
  313.     if ((slptr = db_select(NULL)) == NULL)
  314.         return (FALSE);
  315.  
  316.     /* make sure that the rest of the line is blank */
  317.     if (!db_flush()) {
  318.         db_done(slptr);
  319.         return (FALSE);
  320.     }
  321.  
  322.     /* loop through the selected tuples */
  323.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  324.  
  325.         /* print separator if not the first tuple */
  326.         if (tcnt != 0)
  327.             printf("----\n");
  328.  
  329.     /* loop through the selected attributes */
  330.     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  331.  
  332.         /* get the attribute pointer */
  333.         aptr = saptr->sa_attr;
  334.  
  335.         /* get the attribute name */
  336.         strncpy(aname,aptr->at_name,ANSIZE); aname[ANSIZE] = 0;
  337.  
  338.         /* get the attribute value */
  339.         db_aget(aptr,saptr->sa_aptr,avalue);
  340.         for (ap = avalue; isspace(*ap); ap++)
  341.         ;
  342.  
  343.         /* print it */
  344.         if (strlen(aname) < 8)
  345.         printf("%s\t\t: %s\n",aname,ap);
  346.         else
  347.         printf("%s\t: %s\n",aname,ap);
  348.  
  349.             /* setup null prompt strings */
  350.             db_prompt(NULL,NULL);
  351.  
  352.         /* prompt and input attribute value */
  353.         while (TRUE) {
  354.         if (strlen(aname) < 8)
  355.             printf("%s\t\t: ",aname);
  356.         else
  357.             printf("%s\t: ",aname);
  358.         if (db_gline(avalue) != NULL)
  359.             break;
  360.         }
  361.  
  362.         /* store the attribute value */
  363.         if (avalue[0] != EOS) {
  364.         db_aput(aptr,saptr->sa_aptr,avalue);
  365.         saptr->sa_srel->sr_update = TRUE;
  366.         }
  367.     }
  368.  
  369.     /* update the tuples */
  370.     db_update(slptr);
  371.     }
  372.  
  373.     /* finish the selection */
  374.     db_done(slptr);
  375.  
  376.     /* check number of tuples updated */
  377.     if (tcnt != 0) {
  378.  
  379.     /* print tuple count */
  380.         printf("[ %d updated ]\n",tcnt);
  381.     }
  382.     else
  383.     printf("[ none updated ]\n");
  384.  
  385.     /* return successfully */
  386.     return (TRUE);
  387. }
  388.  
  389. /* print - print tuples from a set of relations */
  390. static int print()
  391. {
  392.     struct sel *slptr;
  393.     FILE *ffp,*ofp;
  394.     int tcnt;
  395.  
  396.     /* parse the using clause */
  397.     if (!using(&ffp,".frm"))
  398.         return (FALSE);
  399.  
  400.     /* parse the select clause */
  401.     if ((slptr = db_select(NULL)) == NULL)
  402.         return (FALSE);
  403.  
  404.     /* parse the into clause */
  405.     if (!db_to(&ofp,".txt")) {
  406.         db_done(slptr);
  407.         return (FALSE);
  408.     }
  409.  
  410.     /* check for normal or formated output */
  411.     if (ffp == NULL)
  412.         tcnt = table(ofp,slptr);
  413.     else
  414.         tcnt = form(ofp,slptr,ffp);
  415.  
  416.     /* finish the selection */
  417.     db_done(slptr);
  418.  
  419.     /* close the form definition file */
  420.     if (ffp != NULL)
  421.         fclose(ffp);
  422.  
  423.     /* close the output file */
  424.     if (ofp != stdout)
  425.         fclose(ofp);
  426.  
  427.     /* check number of tuples selected */
  428.     if (tcnt != 0)
  429.         printf("[ %d found ]\n",tcnt);
  430.     else
  431.     printf("[ none found ]\n");
  432.  
  433.     /* return successfully */
  434.     return (TRUE);
  435. }
  436.  
  437. /* select - select tuples from a set of relations */
  438. static int select()
  439. {
  440.     struct sel *slptr;
  441.     struct relation *rptr;
  442.     struct sattr *saptr;
  443.     char *rname,*aname,*tbuf;
  444.     int tcnt,abase,i;
  445.  
  446.     /* parse the select clause */
  447.     if ((slptr = db_select(NULL)) == NULL)
  448.         return (FALSE);
  449.  
  450.     /* check for "into <fname>" */
  451.     if (db_token() == INTO) {
  452.     db_ntoken();
  453.     if (db_ntoken() != ID && dbv_token != STRING) {
  454.         db_done(slptr);
  455.         return (FALSE);
  456.     }
  457.     rname = dbv_tstring;
  458.     }
  459.     else
  460.     rname = "sdbcur";
  461.  
  462.     /* create a new relation */
  463.     if ((rptr = db_rcreate(rname)) == NULL) {
  464.         db_done(slptr);
  465.         return (FALSE);
  466.     }
  467.  
  468.     /* create the selected attributes */
  469.     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  470.  
  471.         /* decide which attribute name to use */
  472.         if ((aname = saptr->sa_name) == NULL)
  473.             aname = saptr->sa_aname;
  474.  
  475.     /* add the attribute */
  476.     if (!db_rcattr(rptr,aname,saptr->sa_attr->at_type,
  477.                       saptr->sa_attr->at_size)) {
  478.         free(rptr);
  479.             db_done(slptr);
  480.         return (FALSE);
  481.     }
  482.     }
  483.  
  484.     /* create the relation header */
  485.     if (!db_rcheader(rptr,50)) {
  486.         db_done(slptr);
  487.         return (FALSE);
  488.     }
  489.  
  490.     /* allocate and initialize a tuple buffer */
  491.     if ((tbuf = calloc(1,rptr->rl_size)) == NULL) {
  492.         db_rcdone(rptr);
  493.     return (db_ferror(INSMEM));
  494.     }
  495.     tbuf[0] = ACTIVE;
  496.  
  497.     /* loop through the selected tuples */
  498.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  499.  
  500.         /* create the tuple from the selected attributes */
  501.         abase = 1;
  502.         for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  503.             for (i = 0; i < saptr->sa_attr->at_size; i++)
  504.             tbuf[abase + i] = saptr->sa_aptr[i];
  505.             abase += i;
  506.         }
  507.     
  508.         /* write the tuple */
  509.         if (write(rptr->rl_fd,tbuf,rptr->rl_size) != rptr->rl_size) {
  510.             db_rcdone(rptr);
  511.         free(tbuf);
  512.         return (db_ferror(INSBLK));
  513.     }
  514.         rptr->rl_tcnt++;
  515.         rptr->rl_tmax++;
  516.     }
  517.  
  518.     /* finish the selection */
  519.     db_done(slptr);
  520.  
  521.     /* finish relation creation */
  522.     if (!db_rcdone(rptr))
  523.         return (FALSE);
  524.  
  525.     /* check number of tuples selected */
  526.     if (tcnt != 0)
  527.         printf("[ %d found ]\n",tcnt);
  528.     else
  529.     printf("[ none found ]\n");
  530.  
  531.     /* return successfully */
  532.     return (TRUE);
  533. }
  534.  
  535. /* mc_define - define a macro */
  536. static int mc_define()
  537. {
  538.     struct macro *mptr,*mlast;
  539.     struct mtext *tptr,*tlast;
  540.     char textline[LINEMAX+1];
  541.  
  542.     /* get macro name */
  543.     if (db_xntoken() != ID)
  544.     return (db_ferror(SYNTAX));
  545.  
  546.     /* make sure that the rest of the line is blank */
  547.     if (!db_flush())
  548.         return (FALSE);
  549.  
  550.     /* find the macro in the macro table and free it */
  551.     for (mptr = dbv_macros, mlast = NULL; mptr != NULL; mlast = mptr, mptr = mptr->mc_next)
  552.         if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
  553.             if (mlast == NULL)
  554.             dbv_macros = mptr->mc_next;
  555.             else
  556.             mlast->mc_next = mptr->mc_next;
  557.             mc_free(mptr);
  558.         }
  559.  
  560.     /* allocate and initialize a macro structure */
  561.     if ((mptr = (struct macro *)malloc(sizeof(struct macro))) == NULL)
  562.         return (db_ferror(INSMEM));
  563.     if ((mptr->mc_name = malloc(strlen(dbv_tstring)+1)) == NULL) {
  564.         free(mptr);
  565.         return (db_ferror(INSMEM));
  566.     }
  567.     strcpy(mptr->mc_name,dbv_tstring);
  568.     mptr->mc_mtext = NULL;
  569.  
  570.     /* setup null prompt strings */
  571.     db_prompt(NULL,"SDB-DEF> ");
  572.  
  573.     /* get definition text */
  574.     for (tlast = NULL; ; tlast = tptr) {
  575.  
  576.         /* get a line */
  577.         db_gline(textline);
  578.         if (textline[0] == EOS || textline[0] == '\n')
  579.             break;
  580.  
  581.         /* allocate a macro text structure */
  582.         if ((tptr = (struct mtext *)malloc(sizeof(struct mtext))) == NULL) {
  583.             mc_free(mptr);
  584.             return (db_ferror(INSMEM));
  585.         }
  586.         if ((tptr->mt_text = malloc(strlen(textline)+1)) == NULL) {
  587.             mc_free(mptr);
  588.             return (db_ferror(INSMEM));
  589.         }
  590.         strcpy(tptr->mt_text,textline);
  591.         tptr->mt_next = NULL;
  592.  
  593.         /* link it into the macro list */
  594.         if (tlast == NULL)
  595.             mptr->mc_mtext = tptr;
  596.         else
  597.             tlast->mt_next = tptr;
  598.     }
  599.  
  600.     /* link the new macro into the macro list */
  601.     if (tlast == NULL)
  602.         mc_free(mptr);
  603.     else {
  604.         mptr->mc_next = dbv_macros;
  605.         dbv_macros = mptr;
  606.     }
  607.  
  608.     /* return successfully */
  609.     return (TRUE);
  610. }
  611.  
  612. /* mc_show - show a macro */
  613. static int mc_show()
  614. {
  615.     struct macro *mptr;
  616.     struct mtext *tptr;
  617.  
  618.     /* get macro name */
  619.     if (db_xntoken() != ID)
  620.     return (db_ferror(SYNTAX));
  621.  
  622.     /* find the macro in the macro table */
  623.     for (mptr = dbv_macros; mptr != NULL; mptr = mptr->mc_next)
  624.         if (db_scmp(mptr->mc_name,dbv_tstring) == 0) {
  625.             for (tptr = mptr->mc_mtext; tptr != NULL; tptr = tptr->mt_next)
  626.             printf("\t%s\n",tptr->mt_text);
  627.             break;
  628.         }
  629.  
  630.     /* check for successful search */
  631.     if (mptr == NULL)
  632.         printf("*** no macro named: %s ***\n",dbv_tstring);
  633.  
  634.     /* return successfully */
  635.     return (TRUE);
  636. }
  637.  
  638. /* mc_free - free a macro definition */
  639. static mc_free(mptr)
  640.   struct macro *mptr;
  641. {
  642.     struct mtext *tptr;
  643.  
  644.     while ((tptr = mptr->mc_mtext) != NULL) {
  645.     mptr->mc_mtext = tptr->mt_next;
  646.     free(tptr->mt_text);
  647.     free(tptr);
  648.     }
  649.     free(mptr->mc_name);
  650.     free(mptr);
  651. }
  652.  
  653. /* db_to - redirect output into a file */
  654. int db_to(pfp,ext)
  655.   FILE **pfp; char *ext;
  656. {
  657. #ifdef vms
  658.     int fd;
  659. #endif
  660.  
  661.     /* assume no into clause */
  662.     *pfp = stdout;
  663.  
  664.     /* check for "into <fname>" */
  665.     if (db_token() != INTO)
  666.         return (TRUE);
  667.     db_ntoken();
  668.     if (db_ntoken() == ID)
  669.         strcat(dbv_tstring,ext);
  670.     else if (dbv_token != STRING)
  671.         return (db_ferror(SYNTAX));
  672.  
  673.     /* open the output file */
  674. #ifdef vms
  675.     if ((fd = creat(dbv_tstring,0,"rfm=var","rat=cr")) == -1)
  676.         return (db_ferror(OUTCRE));
  677.     *pfp = fdopen(fd,"w");
  678. #else
  679.     if ((*pfp = fopen(dbv_tstring,"w")) == NULL)
  680.         return (db_ferror(OUTCRE));
  681. #endif
  682.  
  683.     /* return successfully */
  684.     return (TRUE);
  685. }
  686.  
  687. /* using - get form definition file spec */
  688. static int using(pfp,ext)
  689.   FILE **pfp; char *ext;
  690. {
  691.     /* assume no using clause */
  692.     *pfp = NULL;
  693.  
  694.     /* check for "using <fname>" */
  695.     if (db_token() != USING)
  696.         return (TRUE);
  697.     db_ntoken();
  698.     if (db_ntoken() == ID)
  699.         strcat(dbv_tstring,ext);
  700.     else if (dbv_token != STRING)
  701.         return (db_ferror(SYNTAX));
  702.  
  703.     /* open the input file */
  704.     if ((*pfp = fopen(dbv_tstring,"r")) == NULL)
  705.         return (db_ferror(INPFNF));
  706.  
  707.     /* return successfully */
  708.     return (TRUE);
  709. }
  710.  
  711. /* table - output a relation table */
  712. static int table(fp,slptr)
  713.   FILE *fp; struct sel *slptr;
  714. {
  715.     int tcnt;
  716.  
  717.     /* loop through the selected tuples */
  718.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  719.  
  720.     /* print table head on first tuple selected */
  721.     if (tcnt == 0)
  722.         db_thead(fp,slptr);
  723.  
  724.     /* print the tuple */
  725.     db_tentry(fp,slptr);
  726.     }
  727.  
  728.     /* print table foot */
  729.     if (tcnt != 0)
  730.         db_tfoot(fp,slptr);
  731.  
  732.     /* return the tuple count */
  733.     return (tcnt);
  734. }
  735.  
  736. /* form - process a form */
  737. static int form(ofp,slptr,ffp)
  738.   FILE *ofp; struct sel *slptr; FILE *ffp;
  739. {
  740.     char aname[ANSIZE+1];
  741.     int ch,tcnt;
  742.  
  743.     /* loop through the selected tuples */
  744.     for (tcnt = 0; db_fetch(slptr); tcnt++) {
  745.  
  746.     /* reposition the form definition file */
  747.     fseek(ffp,0L,0);
  748.  
  749.     /* process the form */
  750.     while ((ch = getc(ffp)) != -1)
  751.         if (ch == '<') {
  752.         get_aname(ffp,aname);
  753.         put_avalue(ofp,slptr,aname);
  754.         }
  755.         else
  756.         putc(ch,ofp);
  757.     }
  758.  
  759.     /* return the tuple count */
  760.     return (tcnt);
  761. }
  762.  
  763. /* get_aname - get an attribute name */
  764. static get_aname(fp,aname)
  765.   FILE *fp; char *aname;
  766. {
  767.     int ch;
  768.  
  769.     while ((ch = getc(fp)) != '>')
  770.     if (!isspace(ch))
  771.             *aname++ = ch;
  772.     *aname = 0;
  773. }
  774.  
  775. /* put_avalue - output attribute value */
  776. static put_avalue(fp,slptr,aname)
  777.   FILE *fp; struct sel *slptr; char *aname;
  778. {
  779.     struct sattr *saptr;
  780.     char *saname;
  781.     int i;
  782.  
  783.     /* loop through the selected attributes */
  784.     for (saptr = slptr->sl_attrs; saptr != NULL; saptr = saptr->sa_next) {
  785.  
  786.     /* check the selected attribute name */
  787.     if ((saname = saptr->sa_name) == NULL)
  788.         saname = saptr->sa_aname;
  789.     if (db_scmp(saname,aname) == 0)
  790.         break;
  791.     }
  792.  
  793.     if (saptr == NULL) {
  794.     fprintf(fp,"<error>");
  795.     return;
  796.     }
  797.  
  798.     /* get the attribute value */
  799.     for (i = 0; i < saptr->sa_attr->at_size; i++)
  800.         if (saptr->sa_aptr[i] != 0)
  801.             putc(saptr->sa_aptr[i],fp);
  802.         else
  803.             putc(' ',fp);
  804. }
  805.  
  806. /* set - set internal parameters */
  807. static int set()
  808. {
  809.     int value;
  810.  
  811.     /* process each set request */
  812.     while (db_token() == ID) {
  813.  
  814.         /* skip the identifier */
  815.         db_ntoken();
  816.  
  817.         /* check for "no" */
  818.         if (db_scmp(dbv_tstring,"no") == 0) {
  819.             value = FALSE;
  820.             if (db_token() != ID)
  821.             return (db_ferror(BADSET));
  822.             db_ntoken();
  823.         }
  824.         else
  825.             value = TRUE;
  826.  
  827.         /* check for parameter to set */
  828.         if (db_scmp(dbv_tstring,"fold") == 0)
  829.             dbv_fold = value;
  830.         else
  831.             return (db_ferror(BADSET));
  832.     }
  833.  
  834.     /* return successfully */
  835.     return (TRUE);
  836. }
  837.